﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Agrement;
using analy;
using System.Threading.Tasks;
using System.Net.Http;
using System.Web.Script.Serialization;
using System.Net.Sockets;

namespace SockLib.Device
{
    class STANDMODBUS:IDevice 
    {
        /// <summary>
        /// 外部传进来的参数
        /// </summary>
        Dictionary<string, object> Par = new Dictionary<string, object>();
        public void SetParars(Dictionary<string, object> Params)
        {
            Par = Params;
        }

        public STANDMODBUS()
        {
            
        }

        JavaScriptSerializer JS = new JavaScriptSerializer();
        #region 注册处理
        /// <summary>
        /// 收到数据是否满足注册条件
        /// </summary>
        /// <param name="Buffer">Socket收到的数据</param>
        /// <param name="DM">如果成功解析，DM写入相应信息</param>
        /// <returns>True：成功解析，False：未能解析（乱数据）</returns>
        public bool DeviceReg(byte[] Buffer, ref DeviceModel DM, out List<DeviceModel.SendMsg> Sendinfo)
        {
            try
            {
                Sendinfo = new List<DeviceModel.SendMsg>();
                DeviceModel DeviceModel = new DeviceModel();
                ModbusReg RegMsg;
                if (!RegRull(Buffer, out RegMsg) && !RegDevice(Buffer, out RegMsg))
                {
                    return false;  //未能解析，返回失败
                }
                DeviceModel.Uid = RegMsg.reg_id;
                DeviceModel.DeviceGroup = DeviceModel.Uid.Substring(1, 4); //获取组号
                DeviceModel.MobileNo = RegMsg.phone;  //获得手机号
                DM = DeviceModel;
                DeviceModel.SendMsg DS = new DeviceModel.SendMsg();
                DS.TargetUid = DeviceModel.Uid;
                DS.DeviceOper = Converts.DeviceOper.Register;
                DS.SendBuffer = System.Text.Encoding.Default.GetBytes(JS.Serialize(RegMsg));
                if (Convert.ToInt16(DeviceModel.Uid.Substring(0, 1)) == 1)  //第1位是1中心，其他节点
                {
                    DeviceModel.IsCenter = true;
                    DeviceType = "modbus主站";
                    IsCenter = true;
                    Sendinfo.Add(DS);
                }
                else
                {
                    DeviceModel.IsCenter = false;
                    IsCenter = false;
                    DeviceType = "modbus从站";
                }

                return true;   //返回注册成功
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 是否是中心
        /// </summary>
        public bool IsCenter { get; set; }

        /// <summary>
        /// 设备类型
        /// </summary>
        string DeviceType { get; set; }

        /// <summary>
        /// 返回设备类型
        /// </summary>
        /// <returns></returns>
        string IDevice.DeviceType()
        {
            return DeviceType;
        }

        /// <summary>
        /// 验证是否能注册
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private bool ReadKey(string key)
        {
            //modbuscenter和debug不验证有效性
            if (key == "modbus" || key == "debug")
                return true;
            DataBaseApi.API api = new DataBaseApi.API();
            return api.IsRegisters(key);
            //return true;
        }

        /// <summary>
        /// <para>身份信息验证</para>
        /// </summary>
        /// <param name="Buffer">SOCKET接收到的数据</param>
        /// <param name="reg">JSON反序列得到的对象</param>
        /// <returns></returns>
        private bool RegRull(byte[] Buffer, out ModbusReg reg)
        {
            reg = new ModbusReg();
            try
            {
                List<byte[]> RegList = new List<byte[]>();
                RegList = GetJson(Buffer);
                if (RegList.Count > 0)
                {
                    foreach (byte[] msg in RegList)
                    {
                        string rec = System.Text.Encoding.Default.GetString(msg);
                        ModbusReg MM = JS.Deserialize<ModbusReg>(rec);
                        if ((MM.reg_id == null) || (MM.phone == null) || (MM.user_key == null) || MM.reg_id.Length < 8 || MM.reg_id.Length > 11)
                        {
                            return false;
                        }
                        if (!ReadKey(MM.user_key))  //需要验证
                            return false;
                        reg = MM;
                    }
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                logexception.WriteLogToFile(ex);
                string msg = ex.Message;
                return false;
            }
        }

        /// <summary>
        /// <para>字符串注册，仅能注册节点,格式如下</para>
        /// <para>MB#SOCKETID#PHONE#DEVICETYPE</para>
        /// <para>MB:固定头，SOCKETID：8-11位注册的编号，PHONE：11位手机号，DEVICETYPE：1-2位设备类型识别</para>
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="reg"></param>
        /// <returns></returns>
        private bool RegDevice(byte[] buffer, out ModbusReg reg)
        {
            reg = new ModbusReg();
            try
            {
                string rec = System.Text.Encoding.Default.GetString(buffer);
                string[] res = rec.Split('#');
                if (res.Length == 3 && res[0] == "MB" && res[1].Length >= 8 && res[1].Length <= 11 && res[2].Length == 11 &&
                   CommVoid.IsInteger(res[1]) && CommVoid.IsInteger(res[2]) && res[1].Substring(0, 1) != "1")
                {
                    reg.phone = res[2];
                    reg.reg_id = res[1];
                }
                else
                    return false;
                return true;
            }
            catch (Exception)
            {

                return false;
            }
        }

        /// <summary>
        /// 收到byte[]中，把{}中的数据变成list<byte[]>中一项
        /// </summary>
        /// <param name="reg">注册的数组</param>
        /// <returns></returns>
        private List<byte[]> GetJson(byte[] reg)
        {
            List<byte> ReadJson = new List<byte>();
            ReadJson.AddRange(reg);
            List<byte[]> RetJson = new List<byte[]>();
            while (ReadJson.Count > 0)
            {
                int StartCharInt = 0;
                int EndCharInt = 0;
                if (ReadJson[0] == 0x7b)
                {
                    List<byte> readbyte = new List<byte>();
                    int RemoveCount = 0;
                    for (int i = 0; i < ReadJson.Count; i++)
                    {
                        if (ReadJson[i] == 0x7b)
                            StartCharInt += 1;
                        if (ReadJson[i] == 0x7d)
                            EndCharInt += 1;
                        readbyte.Add(ReadJson[i]);
                        if (StartCharInt == EndCharInt)
                        {
                            RetJson.Add(readbyte.ToArray());
                            ReadJson.RemoveRange(0, i);
                            RemoveCount = i;
                            break;
                        }
                    }
                    if (RemoveCount == 0)
                        ReadJson.RemoveAt(0);
                }
                else
                    ReadJson.RemoveAt(0);
            }
            return RetJson;
        }
        #endregion


        #region 获取数据转发结构
        /// <summary>
        /// 中心数据转发规则,数据发送给节点(中心执行代码）
        /// </summary>
        /// <param name="ReceiveData"></param>
        public bool TransferRule(byte[] ReceiveData, out List<DeviceModel.SendMsg> Sendinfo)
        {
            Sendinfo = new List<DeviceModel.SendMsg>();
            List<byte[]> JSONSTR = new List<byte[]>();
            JSONSTR = GetJson(ReceiveData);
            foreach (byte[] msg in JSONSTR)
            {
                string rec = System.Text.Encoding.Default.GetString(msg);
                ModbusSend MM = JS.Deserialize<ModbusSend>(rec);
                if (MM.socket_id == null)
                {
                    continue;
                }
                DeviceModel.SendMsg DS = new Device.DeviceModel.SendMsg();
                DS.TargetUid = MM.socket_id;
                //DS.TargetUid = "-1";
                byte[] SendBytes = getModBusData(MM);
                if (SendBytes != null)
                {
                    DS.SendBuffer = SendBytes;
                    DS.DeviceOper = Converts.DeviceOper.Transfer;
                    //int[] modbupara = new int[] { MM.device_id, MM.Device_type };
                    //DS.Params = modbupara;
                    ModbusDevices.ModBusDevice.SaveDevice(Par["IP"].ToString(), MM.socket_id, MM.device_id, MM.Device_type);
                    Sendinfo.Add(DS);
                }

            }

            if (Sendinfo.Count > 0)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 组合modbus数据帧
        /// </summary>
        /// <param name="MS"></param>
        /// <returns></returns>
        private byte[] getModBusData(ModbusSend MS)
        {
            List<byte> LB = new List<byte>();
            if (MS.wireless_id > 0 && MS.wireless_id < 65536)
            {
                LB.Add((byte)(MS.wireless_id / 256));
                LB.Add((byte)(MS.wireless_id % 256));
            }
            LB.Add((byte)MS.device_id);   //写入设备ID
            LB.Add((byte)MS.device_cmd);  //写入命令
            LB.Add((byte)(MS.device_startreg / 256));  //写入起始地址高位
            LB.Add((byte)(MS.device_startreg % 256));  //写入其实地址低位
            if (MS.device_reglength > 0)   //读寄存器指令
            {  //MS.device_reglength>0就表示是读指令，忽略MS.device_WriteData中内容
                LB.Add((byte)(MS.device_reglength / 256));  //写入读取寄存器个数高位
                LB.Add((byte)(MS.device_reglength % 256));  //写入读取寄存器个数低位
            }
            else if (MS.device_WriteData.Length == 1)  //写单个寄存器
            {
                LB.Add((byte)(MS.device_WriteData[0] / 256));
                LB.Add((byte)(MS.device_WriteData[0] % 256));
            }
            else if (MS.device_WriteData.Length > 1)  //写多个寄存器,个数必须是2的N倍才能写入
            {
                LB.Add((byte)(MS.device_WriteData.Length / 256));  //写寄存器个数高位
                LB.Add((byte)(MS.device_WriteData.Length % 256));//写寄存器个数低位
                LB.Add((byte)(MS.device_WriteData.Length * 2));  //写入的数据长度
                for (int i = 0; i < MS.device_WriteData.Length; i++)
                {
                    LB.Add((byte)(MS.device_WriteData[i] / 256));  //写入数据高位
                    LB.Add((byte)(MS.device_WriteData[i] % 256));//写入数据高位
                }

            }
            else
            {
                LB.Clear();
                return LB.ToArray();
            }
            LB.AddRange(CRC.GetCRC(LB.ToArray(), MS.IsLowBitFirst));   //获得CRC校验          
            return LB.ToArray();
        }



        /// <summary>
        /// 节点数据转发规则,数据发送给中心（节点执行代码）
        /// </summary>
        /// <param name="ReceiveData">收到的数据</param>
        /// <param name="uid">GPRS的编号</param>
        /// <param name="Sendinfo">需要转发的结构体</param>
        /// <returns></returns>
        public bool NodeTransferRule(byte[] ReceiveData, string uid, ref DeviceModel.SendMsg[] Sendinfos)
        {
            List<DeviceModel.SendMsg> LDS = new List<DeviceModel.SendMsg>();
            ModbusData res = new ModbusData();
            res.socket_id = uid;
            if (Sendinfos[0].Params.GetType() == typeof(SocketModel))
            {
                STANDMODBUS Modbus = (STANDMODBUS)((SocketModel)Sendinfos[0].Params).RegDevice;  //获得驱动处理模块
                ModbusDevices.MBType device = Modbus.GetDevice(Par["IP"].ToString(),uid,  ReceiveData[0]);
                if (!device.DataAnaly(ReceiveData, ref res))
                {
                    device = new ModbusDevices.AnalyError (device.GetDeviceId ());
                    device.DataAnaly(ReceiveData, ref res);
                }
            }
            else
                return false;
            Device.DeviceModel.SendMsg Sendinfo = new Device.DeviceModel.SendMsg();
            Sendinfo.TargetUid = uid;
            Sendinfo.SendBuffer = System.Text.Encoding.Default.GetBytes(JS.Serialize(res));
            Sendinfo.DeviceOper = Converts.DeviceOper.Transfer;
            LDS.Add(Sendinfo);
            Sendinfos = LDS.ToArray();
            return true;
        }

        /// <summary>
        /// <para>以设备ID号作为检索条件查找是否有符合的设备驱动，未找到设置为0</para>
        /// <para>新增设备驱动需要在这里添加case条件语句</para>
        /// </summary>
        /// <param name="deviceid">返回驱动程序</param>
        /// <returns></returns>
        ModbusDevices.MBType GetDevice(string ip, string gprs, byte deviceid)
        {
            int device = ModbusDevices.ModBusDevice.GetDevice(ip, gprs, deviceid);
            switch (device)
            {
                case 0:
                    return new ModbusDevices.UnKnow();
                case 1:
                    return new ModbusDevices.GreenHouse();
                case 2:
                    return new ModbusDevices.CSPump();
                default:
                    return new ModbusDevices.UnKnow();
            }

        }

        #endregion


        #region 数据转换

        /// <summary>
        /// 心跳包格式
        /// </summary>
        /// <param name="TargetUid">发给的中心模块ID</param>
        /// <param name="uid">在线中心模块ID集合</param>
        /// <returns></returns>
        public List<byte[]> HeartBeatConvert(string TargetUid, string[] uid)
        {
            //if (Devices != null )
            //    return null;
            JSON_HEARTBEAT JH = new JSON_HEARTBEAT();
            JH.targetuid = TargetUid;
            JH.uid = uid;
            string s = JS.Serialize(JH);
            List<byte[]> LB = new List<byte[]>();
            LB.Add(System.Text.Encoding.Default.GetBytes(s));
            return LB;
            //List<byte[]> L = new List<byte[]>();
            //byte[] b = new byte[] { 0x2b };
            //L.Add(b);
            //return L;
        }


        /// <summary>
        /// 发送数据转换
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        public byte[] SendDataConvert(byte[] Data)
        {
            return Data;
        }

        /// <summary>
        /// 接收数据转换
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        public byte[] ReceiveDataConvert(byte[] Data)
        {
            return Data;
        }

        public byte[] DataPacket(DeviceModel.SendMsg SendMsg)
        {
            //if (!IsCenter && SendMsg.Params != null && SendMsg.Params.GetType() == typeof(int[]))
            //{
            //    int[] Types = (int[])SendMsg.Params;
            //}
            return SendMsg.SendBuffer;
        }
        #endregion



        #region 心跳包处理
        /// <summary>
        /// 心跳包不做任何转发处理
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public bool IsHeartPack(byte[] Pack)
        {
            if (Pack.Length == 1 && (Pack[0] == 0x2B || Pack[0] == 0xfe))
                return true;
            return false;

        }
        #endregion

        #region 显示LOG区发送数据
        public string SendString(string uid, byte[] msg)
        {
            if (uid.Substring(0, 1) == "1")
                return System.Text.Encoding.Default.GetString(msg);
            else
                return Converts.byteToHexStr(msg);
        }

        #endregion
    }
}
